home *** CD-ROM | disk | FTP | other *** search
/ Micromanía 92 / CDMM92_1.ISO / SOF 2 SDK / sof2sdk-101.msi / _92D6AC311BB48EBA344BBABC89DA6AB0 / _3DF3BE7E47304071B81338206CA62365 < prev    next >
Encoding:
Text File  |  2002-06-14  |  29.0 KB  |  1,134 lines

  1. // Copyright (C) 2001-2002 Raven Software.
  2. //
  3. // cg_newdraw.c --
  4.  
  5. #include "cg_local.h"
  6. #include "../game/bg_public.h"
  7. #include "../ui/ui_shared.h"
  8.  
  9. extern displayContextDef_t cgDC;
  10.  
  11. static float healthColors[4][4] = 
  12. {
  13.   { 1.0f, 0.69f, 0.0f, 1.0f } ,        // normal
  14.   { 1.0f, 0.2f, 0.2f, 1.0f },        // low health
  15.   { 0.5f, 0.5f, 0.5f, 1.0f},        // weapon firing
  16.   { 1.0f, 1.0f, 1.0f, 1.0f }         // health > 100
  17. };
  18.  
  19. static void CG_DrawPlayerLocation( rectDef_t *rect, float scale, vec4_t color, int textStyle  ) 
  20. {
  21.     clientInfo_t *ci = &cgs.clientinfo[cg.snap->ps.clientNum];
  22.     const char   *s;
  23.   
  24.     if (!ci)
  25.     {
  26.         return;
  27.     }
  28.     
  29.     s = CG_ConfigString(CS_LOCATIONS + ci->location);
  30.  
  31.     if (!s || !*s) 
  32.     {
  33.         s = "unknown";
  34.     }
  35.  
  36.     CG_DrawText(rect->x, rect->y + rect->h, cgs.media.hudFont, scale, color, s, 0, 0 );
  37. }
  38.  
  39. //==============================================================================
  40. //    CG_DrawPlayerSniperBullet
  41. //==============================================================================
  42. static void CG_DrawPlayerSniperBullet ( rectDef_t* rect, qhandle_t shader, int bullet )
  43. {
  44.     // Dont draw the bullet if the player doesnt have enough ammo
  45.     if ( bullet > cg.predictedPlayerState.clip[ATTACK_NORMAL][WP_MSG90A1] )
  46.     {
  47.         return;
  48.     }
  49.  
  50.     CG_DrawStretchPic ( rect->x, rect->y, rect->w, rect->h, 0, 0, 1, 1, NULL, shader );
  51. }
  52.  
  53. //==============================================================================
  54. //    CG_DrawPlayerSniperMagnification
  55. //==============================================================================
  56. static void CG_DrawPlayerSniperMagnification ( rectDef_t *rect, qhandle_t font, float scale, vec4_t color )
  57. {
  58.     const char* mag;
  59.  
  60.     switch ( cg.predictedPlayerState.zoomFov )
  61.     {
  62.         default:
  63.         case 20:    mag = "5x";            break;
  64.         case 10:    mag = "10x";        break;
  65.         case 5:        mag = "20x";        break;
  66.     }    
  67.  
  68.     // Center the text
  69.     CG_DrawText (rect->x, rect->y, font, scale, color, mag, 0, 0 );
  70. }
  71.  
  72. //==============================================================================
  73. //    CG_DrawPlayerWeaponName
  74. //==============================================================================
  75. static void CG_DrawPlayerWeaponName ( rectDef_t *rect, qhandle_t font, float scale, vec4_t color  )
  76. {
  77.     float        width;
  78.     const char*    name;
  79.  
  80.     if( cg.weaponSelect > WP_NONE )
  81.     {
  82.         // Equipped weapon
  83.         name = weaponData[cg.weaponSelect].classname;
  84.     }
  85.     else
  86.     {
  87.         // No weapon equipped.
  88.         name = "NONE";
  89.     }
  90.  
  91.     // Get the width of the text so we can center it
  92.     width = trap_R_GetTextWidth ( name, font, scale, 0 );
  93.     
  94.     // Center the text
  95.     CG_DrawText (rect->x + (rect->w - width) / 2, rect->y + rect->h, font, scale, color, name, 0, 0 );
  96. }
  97.  
  98. //==============================================================================
  99. //    CG_DrawPlayerWeaponName
  100. //==============================================================================
  101. static void CG_DrawPlayerAltWeaponName ( rectDef_t *rect, qhandle_t font, float scale, vec4_t color )
  102. {
  103.     float        width;
  104.     const char*    name;
  105.  
  106.     if( cg.weaponSelect > WP_NONE )
  107.     {
  108.         // Equipped weapon
  109.         name = weaponData[cg.weaponSelect].attack[ATTACK_ALTERNATE].name;
  110.     }
  111.     else
  112.     {
  113.         // No weapon equipped.
  114.         name = "NONE";
  115.     }
  116.  
  117.     // Get the width of the text so we can center it
  118.     width = trap_R_GetTextWidth ( name, font, scale, 0 );
  119.     
  120.     // Center the text
  121.     CG_DrawText (rect->x + (rect->w - width) / 2, rect->y + rect->h, font, scale, color, name, 0, 0 );
  122. }
  123.  
  124. //==============================================================================
  125. //    CG_DrawPlayerWeaponAmmo
  126. //==============================================================================
  127. static void CG_DrawPlayerWeaponAmmo(rectDef_t *rect, qhandle_t font, float scale, vec4_t color )
  128. {
  129.     const char *ammo;
  130.     int            value;
  131.     float        width;
  132.  
  133.     // If the client doenst have a selected weapon then dont draw the ammo
  134.     if ( cg.weaponSelect <= WP_NONE ) 
  135.         return;
  136.  
  137.     // Retrieve the ammo value
  138.     value = cg.predictedPlayerState.ammo[weaponData[cg.weaponSelect].attack[ATTACK_NORMAL].ammoIndex];
  139.  
  140.     // If the ammo value is crazy then dont display it
  141.     if ( value <= -1 )
  142.         return;
  143.  
  144.     // Build the ammo string padded with zeros
  145.     ammo = va ( "%03d", value );
  146.  
  147.     // Retrive the width of the ammo string so it can be centered
  148.     width = trap_R_GetTextWidth (ammo, font, scale, 0 );
  149.  
  150.     // Draw the ammo string centered
  151.     CG_DrawText (rect->x + (rect->w - width) / 2, rect->y + rect->h, font, scale, color, ammo, 0, 0 );
  152. }
  153.  
  154. //==============================================================================
  155. //    CG_DrawPlayerAltWeaponAmmo
  156. //==============================================================================
  157. static void CG_DrawPlayerAltWeaponAmmo(rectDef_t *rect, qhandle_t font, float scale, vec4_t color )
  158. {
  159.     const char *ammo;
  160.     int            value;
  161.     float        width;
  162.  
  163.     // If the client doenst have a selected weapon then dont draw the ammo
  164.     if ( cg.weaponSelect <= WP_NONE ) 
  165.         return;
  166.  
  167.     // If the selected weapon doesn't have an altclip, don't draw.
  168.     if(weaponData[cg.weaponSelect].attack[ATTACK_ALTERNATE].clipSize<=0)
  169.         return;
  170.  
  171.     // Retrieve the ammo value
  172.     value  = cg.predictedPlayerState.ammo[weaponData[cg.weaponSelect].attack[ATTACK_ALTERNATE].ammoIndex];
  173.     value += cg.predictedPlayerState.clip[ATTACK_ALTERNATE][cg.weaponSelect];
  174.     
  175.     // If the ammo value is crazy then dont display it
  176.     if ( value <= -1 )
  177.         return;
  178.  
  179.     // Build the ammo string padded with zeros
  180.     ammo = va ( "%03d", value );
  181.  
  182.     // Retrive the width of the ammo string so it can be centered
  183.     width = trap_R_GetTextWidth (ammo, font, scale, 0 );
  184.  
  185.     // Draw the ammo string centered
  186.     CG_DrawText (rect->x + (rect->w - width) / 2, rect->y + rect->h, font, scale, color, ammo, 0, 0 );
  187. }
  188.  
  189. //==============================================================================
  190. //    CG_DrawPlayerAltWeaponAmmoIcon
  191. //==============================================================================
  192. static void CG_DrawPlayerAltWeaponAmmoIcon(rectDef_t *rect, vec4_t color )
  193. {
  194.     vec4_t fade;
  195.  
  196.     // If the client doenst have a selected weapon then dont draw the ammo icon
  197.     if ( cg.weaponSelect <= WP_NONE ) 
  198.         return;
  199.  
  200.     // If there is no loaded icon then dont draw it
  201.     if ( !cg_weapons[cg.weaponSelect].attack[ATTACK_ALTERNATE].ammoIcon )
  202.     {
  203.         return;
  204.     }
  205.  
  206.     // Fade out the icon if there isnt anything in the alt clip
  207.     fade[0] = color[0];
  208.     fade[1] = color[1];
  209.     fade[2] = color[2];
  210.     fade[3] = color[3] * (cg.predictedPlayerState.clip[ATTACK_ALTERNATE][cg.weaponSelect]?1:0.20f);
  211.  
  212.     trap_R_SetColor ( fade );
  213.  
  214.     // Draw the icon
  215.     CG_DrawPic ( rect->x, rect->y, rect->w, rect->h, cg_weapons[cg.weaponSelect].attack[ATTACK_ALTERNATE].ammoIcon );
  216.  
  217.     // Back to no color
  218.     trap_R_SetColor ( NULL );
  219. }
  220.  
  221. //==============================================================================
  222. //    CG_DrawPlayerWeaponClip
  223. //==============================================================================
  224. static void CG_DrawPlayerWeaponClip (rectDef_t *rect, qhandle_t font, float scale, vec4_t color )
  225. {
  226.     const char *clip;
  227.     int            value;
  228.     float        width;
  229.  
  230.     // If the client doenst have a selected weapon then dont draw the ammo
  231.     if ( cg.weaponSelect <= WP_NONE ) 
  232.         return;
  233.  
  234.     // Retrieve the ammo value
  235.     value = cg.predictedPlayerState.clip[ATTACK_NORMAL][cg.weaponSelect];
  236.  
  237.     // If the ammo value is crazy then dont display it
  238.     if ( value <= -1 )
  239.         return;
  240.  
  241.     // Build the clip string padded with zeros
  242.     clip = va ( "%02d", value );
  243.  
  244.     // Retrive the width of the clip string so it can be centered
  245.     width = trap_R_GetTextWidth (clip, font, scale, 0 );
  246.  
  247.     // Draw the clip string centered
  248.     CG_DrawText (rect->x + (rect->w - width) / 2, rect->y + rect->h, font, scale, color, clip, 0, 0 );
  249. }
  250.  
  251. //==============================================================================
  252. //    CG_DrawPlayerWeaponMode
  253. //==============================================================================
  254. static void CG_DrawPlayerWeaponMode ( rectDef_t *rect, qhandle_t font, float scale, vec4_t color )
  255. {
  256.     float        width;
  257.     const char*    mode;
  258.     int            curMode;
  259.  
  260.     // Use the current fire mode for this weapon, if its undefined then find what it will
  261.     // be once its set
  262.     curMode = cg.predictedPlayerState.firemode[cg.weaponSelect];
  263.     if ( curMode == WP_FIREMODE_NONE )
  264.     {
  265.         curMode = BG_FindFireMode ( cg.weaponSelect, ATTACK_NORMAL, WP_FIREMODE_AUTO );
  266.     }
  267.  
  268.     // TODO: Retrieve the real mode
  269.     switch ( curMode )
  270.     {
  271.         case WP_FIREMODE_NONE:
  272.             mode = "";
  273.             break;
  274.         case WP_FIREMODE_AUTO:
  275.             mode = "AUTO";
  276.             break;
  277.         case WP_FIREMODE_BURST:
  278.             mode = "BURST";
  279.             break;
  280.         case WP_FIREMODE_SINGLE:
  281.             mode = "SINGLE";
  282.             break;
  283.         default:
  284.             // This shouldn't happen.
  285.             assert(0);
  286.             mode = "";
  287.     }
  288.  
  289.     // Get the width of the text so we can center it
  290.     width = trap_R_GetTextWidth ( mode, font, scale, 0 );
  291.     
  292.     // Center the text
  293.     CG_DrawText (rect->x + (rect->w - width) / 2, rect->y + rect->h, font, scale, color, mode, 0, 0 );
  294. }
  295.  
  296. //==============================================================================
  297. //    CG_DrawUseIcon
  298. //==============================================================================
  299. void CG_DrawUseIcon ( rectDef_t* rect )
  300. {
  301.     // If not in a use zone then dont bother
  302.     if ( !(cg.predictedPlayerState.pm_flags & PMF_CAN_USE ) )
  303.     {
  304.         return;
  305.     }
  306.  
  307.     CG_DrawStretchPic ( rect->x, rect->y, rect->w, rect->h,0, 0, 1, 1, NULL, 
  308.                         cgs.gameIcons [ cg.predictedPlayerState.stats[STAT_USEICON] ] );
  309.  
  310.     if ( cg.predictedPlayerState.stats[STAT_USETIME] )
  311.     {
  312.         float w = 98.0f * (float)cg.predictedPlayerState.stats[STAT_USETIME] / (float)cg.predictedPlayerState.stats[STAT_USETIME_MAX];
  313.         CG_DrawRect ( rect->x + rect->h + 10, rect->y + 9, 100, rect->h - 18, 1, colorWhite );
  314.         CG_FillRect ( rect->x + rect->h + 11, rect->y + 10, w, rect->h - 20, colorRed );
  315.         CG_DrawRect ( rect->x + rect->h + 11, rect->y + 10, w, rect->h - 20, 1, colorBlack );
  316.     }
  317. }
  318.  
  319. //==============================================================================
  320. //    CG_DrawPlayerGametypeItems
  321. //==============================================================================
  322. void CG_DrawPlayerGametypeItems ( rectDef_t* rect )
  323. {
  324.     float x;
  325.     int      i;
  326.  
  327.     // If not in a use zone then dont bother
  328.     if ( cg.predictedPlayerState.pm_flags & PMF_CAN_USE )
  329.     {
  330.         return;
  331.     }
  332.  
  333.     x = rect->x;
  334.  
  335.     for ( i = 0; i < MAX_GAMETYPE_ITEMS; i ++ )
  336.     {
  337.         // Doesnt have this mission item
  338.         if ( !(cg.predictedPlayerState.stats[STAT_GAMETYPE_ITEMS] & (1<<i)) )
  339.         {
  340.             continue;
  341.         }
  342.  
  343.         if ( !cg_items[i+MODELINDEX_GAMETYPE_ITEM].icon )
  344.         {    
  345.             continue;
  346.         }
  347.  
  348.         CG_DrawPic ( x, rect->y, rect->w, rect->h, cg_items[i+MODELINDEX_GAMETYPE_ITEM].icon );
  349.     
  350.         x += 2;
  351.     }
  352. }
  353.  
  354. //==============================================================================
  355. //    CG_DrawPlayerArmor
  356. //==============================================================================
  357. void CG_DrawPlayerArmor ( rectDef_t* rect )
  358. {
  359.     float x;
  360.     float w;
  361.  
  362.     // Draw the icon
  363.     trap_R_SetColor ( NULL ); 
  364.  
  365.     w = rect->w;
  366.     x = rect->x;
  367.             
  368.     for ( ; w >= rect->h; w -= rect->h, x += rect->h )
  369.     {
  370.         CG_DrawPic ( x, rect->y - rect->h, rect->h, rect->h, cgs.media.armorShader );
  371.     }
  372.  
  373.     if ( w )
  374.     {
  375.         CG_DrawStretchPic ( x, rect->y - rect->h, w, rect->h,
  376.                             0, 0, w/rect->h, 1.0f, NULL, cgs.media.armorShader );
  377.     }
  378. }
  379.  
  380.  
  381. static void CG_DrawPlayerScore( rectDef_t *rect, qhandle_t font, float scale, vec4_t color )
  382. {
  383.     const char* s;
  384.  
  385.     s = va("%03d",cg.snap->ps.persistant[PERS_SCORE]);
  386.  
  387.     CG_DrawText(rect->x + (rect->w - trap_R_GetTextWidth(s,font,scale,0)) / 2, rect->y + rect->h, font, scale, color, s, 0, 0 );
  388. }
  389.  
  390. static void CG_DrawRedScore(rectDef_t *rect, qhandle_t font, float scale, vec4_t color ) 
  391. {
  392.     int  value;
  393.     char num[16];
  394.  
  395.     if ( cgs.scores1 == SCORE_NOT_PRESENT ) 
  396.     {
  397.         Com_sprintf (num, sizeof(num), "-");
  398.     }
  399.     else 
  400.     {
  401.         Com_sprintf (num, sizeof(num), "%i", cgs.scores1);
  402.     }
  403.  
  404.     value = trap_R_GetTextWidth (num, font, scale, 0);
  405.  
  406.     CG_DrawText (rect->x + rect->w - value, rect->y + rect->h, font, scale, color, num, 0, 0 );
  407. }
  408.  
  409. static void CG_DrawBlueScore(rectDef_t *rect, qhandle_t font, float scale, vec4_t color ) 
  410. {
  411.     int  value;
  412.     char num[16];
  413.  
  414.     if ( cgs.scores2 == SCORE_NOT_PRESENT ) 
  415.     {
  416.         Com_sprintf (num, sizeof(num), "-");
  417.     }
  418.     else 
  419.     {
  420.         Com_sprintf (num, sizeof(num), "%i", cgs.scores2);
  421.     }
  422.     
  423.     value = trap_R_GetTextWidth(num, font, scale, 0 );
  424.     CG_DrawText(rect->x + rect->w - value, rect->y + rect->h, font, scale, color, num, 0, 0 );
  425. }
  426.  
  427. #define MSECS_PER_FRAME (1000.0 / 60.0)
  428. #define HUD_FADE_SPEED 0.05
  429.  
  430. float TimeAdjustHUDVal(float mainVal, float dstVal, float factor)
  431. {
  432.     mainVal = mainVal * (1.0 - factor) + dstVal * factor;
  433.     
  434.     //once we get close enough, just finish up
  435.     if(fabs(mainVal - dstVal) < .01)
  436.     {    // if we don't have this, the last few pixels take FOREVER
  437.         mainVal = dstVal;
  438.     }
  439.  
  440.     return mainVal;
  441. }
  442.  
  443. void HandleHUDSegment(float *floorVal, float *ceilVal, float dstVal, float factor)
  444. {
  445.     if(dstVal < *floorVal)
  446.     {
  447.         *floorVal = dstVal;
  448.     }
  449.     else if(dstVal > *floorVal)
  450.     {
  451.         *floorVal = TimeAdjustHUDVal(*floorVal, dstVal, factor);
  452.     }
  453.  
  454.     if(dstVal > *ceilVal)
  455.     {
  456.         *ceilVal = dstVal;
  457.     }
  458.     else if(dstVal < *ceilVal)
  459.     {
  460.         *ceilVal = TimeAdjustHUDVal(*ceilVal, dstVal, factor);
  461.     }
  462. }
  463.  
  464. float CG_GetValue(int ownerDraw) 
  465. {
  466.     centity_t    *cent;
  467.     playerState_t    *ps;
  468.  
  469.     cent = CG_GetEntity ( cg.snap->ps.clientNum );
  470.     ps = &cg.snap->ps;
  471.  
  472.     switch (ownerDraw) 
  473.     {
  474.         case CG_PLAYER_WEAPON_AMMO:
  475.             if ( cent->currentState.weapon ) 
  476.             {
  477.                 return ps->ammo[weaponData[cent->currentState.weapon].attack[ATTACK_NORMAL].ammoIndex];
  478.             }
  479.             break;
  480.  
  481.         case CG_PLAYER_SCORE:
  482.             return cg.snap->ps.persistant[PERS_SCORE];
  483.         
  484.         case CG_PLAYER_HEALTH:
  485.             return ((float) ps->stats[STAT_HEALTH] * 0.01f) + 0.01f;
  486.  
  487.         case CG_PLAYER_HEALTH_FADE:
  488.         {
  489.             static float healthEdge = 0.0;
  490.             static float healthFull = 0.0;
  491.  
  492.             float curHealth    = ps->stats[STAT_HEALTH] * 0.01;
  493.             float adjustFactor = (cg.frametime / MSECS_PER_FRAME) * HUD_FADE_SPEED;
  494.     
  495.             HandleHUDSegment(&healthEdge, &healthFull, curHealth, adjustFactor);
  496.  
  497.             if ( healthFull < 0 )
  498.                 healthFull = 0;
  499.  
  500.             return healthFull;
  501.         }
  502.  
  503.         case CG_PLAYER_ARMOR_FADE:
  504.         {
  505.             static float armorEdge = 0.0;
  506.             static float armorFull = 0.0;
  507.  
  508.             float curArmor     = ps->stats[STAT_ARMOR] * 0.01;
  509.             float adjustFactor = (cg.frametime / MSECS_PER_FRAME) * HUD_FADE_SPEED;
  510.     
  511.             HandleHUDSegment(&armorEdge, &armorFull, curArmor, adjustFactor);
  512.  
  513.             if ( armorFull < 0 )
  514.                 armorFull = 0;
  515.  
  516.             return armorFull;
  517.         }
  518.  
  519.         case CG_PLAYER_ARMOR:
  520.             return ((float) ps->stats[STAT_ARMOR] * 0.01f);;
  521.  
  522.         case CG_RED_SCORE:
  523.             return cgs.scores1;
  524.             break;
  525.         
  526.         case CG_BLUE_SCORE:
  527.             return cgs.scores2;
  528.             break;
  529.     
  530.         default:
  531.             break;
  532.     }
  533.     
  534.     return -1;
  535. }
  536.  
  537. qboolean CG_OwnerDrawDisabled(int flags, const char* param ) 
  538. {
  539.     return qfalse;
  540. }
  541.  
  542. qboolean CG_OwnerDrawVisible(int flags, const char* param ) 
  543. {
  544.     qboolean visible = qtrue;
  545.  
  546.     while ( visible )
  547.     {
  548.         // Player on the red team?
  549.         if ( flags & CG_SHOW_ONREDTEAM )
  550.         {
  551.             visible = cg.predictedPlayerState.persistant[PERS_TEAM]==TEAM_RED?qtrue:qfalse;
  552.             flags &= ~(CG_SHOW_ONREDTEAM);
  553.             continue;
  554.         }
  555.         // Player on the blue team?
  556.         else if ( flags & CG_SHOW_ONBLUETEAM )
  557.         {
  558.             visible = cg.predictedPlayerState.persistant[PERS_TEAM]==TEAM_BLUE?qtrue:qfalse;
  559.             flags &= ~(CG_SHOW_ONBLUETEAM);
  560.         }
  561.         else if ( flags & CG_SHOW_HUD_NIGHTVISION )
  562.         {
  563.             visible = ((cg.predictedPlayerState.pm_flags & PMF_GOGGLES_ON) && cg.predictedPlayerState.stats[STAT_GOGGLES] == GOGGLES_NIGHTVISION && !(cg.predictedPlayerState.pm_flags&PMF_ZOOMED))? qtrue : qfalse;
  564.             flags &= ~(CG_SHOW_HUD_NIGHTVISION);
  565.         }
  566.         else if ( flags & CG_SHOW_HUD_THERMAL )
  567.         {
  568.             visible = ((cg.predictedPlayerState.pm_flags & PMF_GOGGLES_ON) && cg.predictedPlayerState.stats[STAT_GOGGLES] == GOGGLES_INFRARED )? qtrue : qfalse;
  569.             flags &= ~(CG_SHOW_HUD_THERMAL);
  570.         }
  571.         // Only draw the sniper scope when zoomed
  572.         else if ( flags & CG_SHOW_HUD_SNIPERSCOPE )
  573.         {
  574.             visible = (cg.predictedPlayerState.pm_flags&PMF_ZOOMED)?qtrue:qfalse;
  575.             flags &= ~(CG_SHOW_HUD_SNIPERSCOPE);
  576.         }
  577.         // Draw the health as long as we arent zoomed
  578.         else if ( flags & CG_SHOW_HUD_HEALTH )
  579.         {
  580.             visible = cg.showScores ? qfalse : qtrue;
  581.             flags &= ~(CG_SHOW_HUD_HEALTH);
  582.         }
  583.         // Timer
  584.         else if ( flags & CG_SHOW_HUD_TIMER )
  585.         {
  586.             if ( cg.showScores )
  587.             {
  588.                 visible = qfalse;
  589.             }
  590.             else if ( !cg_drawTimer.integer )
  591.             {
  592.                 visible = qfalse;
  593.             }
  594.  
  595.             flags &= ~(CG_SHOW_HUD_TIMER);
  596.         }
  597.         // Should the alternate weapon information be shown?
  598.         else if (flags & (CG_SHOW_PLAYER_ALT_WEAPONINFO|CG_HIDE_PLAYER_ALT_WEAPONINFO) )
  599.         {
  600.             if ( cg.predictedPlayerState.pm_flags & PMF_ZOOMED )
  601.             {
  602.                 visible = qfalse;
  603.             }
  604.  
  605.             if ( cg.showScores )
  606.             {
  607.                 visible = qfalse;
  608.             }
  609.             else
  610.             {
  611.                 if ( !BG_WeaponHasAlternateAmmo ( cg.weaponSelect ) )
  612.                 {
  613.                     visible = qfalse;
  614.                 }
  615.  
  616.                 // Dont show it if we dont have ammo 
  617.                 if ( !cg.predictedPlayerState.ammo[ weaponData[cg.weaponSelect].attack[ATTACK_ALTERNATE].ammoIndex ] &&
  618.                      !cg.predictedPlayerState.clip[ATTACK_ALTERNATE][ cg.weaponSelect ] )
  619.                 {
  620.                     visible = qfalse;
  621.                 }
  622.  
  623.                 // INvert the visible flag for hidden
  624.                 if ( flags & CG_HIDE_PLAYER_ALT_WEAPONINFO )
  625.                 {
  626.                     if ( cg.predictedPlayerState.pm_flags & PMF_ZOOMED )
  627.                     {
  628.                         visible = qfalse;
  629.                     }
  630.                     else
  631.                     {
  632.                         visible = !visible;
  633.                     }
  634.                 }
  635.             }
  636.  
  637.             flags &= ~(CG_SHOW_PLAYER_ALT_WEAPONINFO|CG_HIDE_PLAYER_ALT_WEAPONINFO);    
  638.         }
  639.         // Draw the weapon info when we arent zoomed    
  640.         else if ( flags & CG_SHOW_HUD_WEAPONINFO )
  641.         {
  642.             visible = (cg.showScores||(cg.predictedPlayerState.pm_flags&PMF_ZOOMED))?qfalse:qtrue;
  643.             flags &= ~(CG_SHOW_HUD_WEAPONINFO);            
  644.         }
  645.         else if (flags & CG_SHOW_ANYTEAMGAME) 
  646.         {
  647.             if( !cgs.gametypeData->teams ) 
  648.             {
  649.                 visible = qfalse;
  650.             }
  651.  
  652.             flags &= ~(CG_SHOW_ANYTEAMGAME);    
  653.         }
  654.         else if (flags & CG_SHOW_ANYNONTEAMGAME) 
  655.         {
  656.             if( cgs.gametypeData->teams ) 
  657.             {
  658.                 visible = qfalse;
  659.             }
  660.  
  661.             flags &= ~(CG_SHOW_ANYNONTEAMGAME);    
  662.         }
  663.         else
  664.         {
  665.             break;
  666.         }
  667.     }
  668.  
  669.     return visible;
  670. }
  671.  
  672. static void CG_Draw1stPlace(rectDef_t *rect, qhandle_t font, float scale, vec4_t color ) 
  673. {
  674.     if (cgs.scores1 != SCORE_NOT_PRESENT) 
  675.     {
  676.         CG_DrawText(rect->x, rect->y, font, scale, color, va("%2i", cgs.scores1),0, 0 ); 
  677.     }
  678. }
  679.  
  680. static void CG_Draw2ndPlace(rectDef_t *rect, qhandle_t font, float scale, vec4_t color ) 
  681. {
  682.     if (cgs.scores2 != SCORE_NOT_PRESENT) 
  683.     {
  684.         CG_DrawText(rect->x, rect->y, font, scale, color, va("%2i", cgs.scores2),0, 0 ); 
  685.     }
  686. }
  687.  
  688. // Draw an entire row of weapons for the visual weapon selection menu
  689.  
  690. static void CG_DrawWeaponList(rectDef_t *rect, qhandle_t font, float scale, vec4_t color )
  691. {
  692.     static vec4_t    colorNormal        = { 0.5f, 0.5f, 0.5f, 0.8f };
  693.     static vec4_t    colorShadow        = { 0.0f, 0.0f, 0.0f, 0.25f };
  694.     static vec4_t    colorSelected    = { 204.0f / 255.0f, 222.0f / 255.0f, 159.0f / 255.0f, 0.925f };
  695.     static vec4_t    colorDisabled   = { 0.4f, 0.4f, 0.4f, 0.8f };
  696.  
  697.     centity_t        *cent;
  698.     playerState_t    *ps;
  699.     qhandle_t        icon;
  700.     int                weaponToDraw;
  701.     int            x,y;
  702.     int            w,h;
  703.     int            i,wid;
  704.     int            category, activeCategory;
  705.     char        numStr[3];
  706.     int            category_x[CAT_MAX];
  707.     gitem_t        *item;
  708.     const char    *s;
  709.  
  710.  
  711.     vec4_t        colorDraw;
  712.  
  713.     rect->x = 20;
  714.     rect->y = 65;
  715.     rect->h = 320;
  716.  
  717.     // are we showing weapon menu?
  718.     if (!cg.weaponMenuUp)
  719.     {
  720.         return;
  721.     }
  722.  
  723.     cent = CG_GetEntity ( cg.snap->ps.clientNum );
  724.     ps   = &cg.snap->ps;
  725.  
  726.     // If the menu was up during follow then turn it off
  727.     if ( (ps->pm_flags & PMF_FOLLOW) || ps->pm_type == PM_SPECTATOR )
  728.     {
  729.         cg.weaponMenuUp = qfalse;
  730.         return;
  731.     }
  732.  
  733.  
  734.     h = rect->h / CAT_MAX;
  735.     w = h*2;  // we know that the weapon icons are a 2:1 aspect ratio
  736.  
  737.     activeCategory = -1;
  738.  
  739.     // start at left edge for all weapon categories 
  740.     for (i=CAT_NONE; i<CAT_MAX; i++)
  741.     {
  742.         category_x[i] = rect->x + w;
  743.     }
  744.  
  745.     for (weaponToDraw = WP_NONE + 1; weaponToDraw < WP_NUM_WEAPONS; weaponToDraw++ )
  746.     {
  747.         category = weaponData[weaponToDraw].category;
  748.  
  749.         x = category_x[category];
  750.         y = rect->y + (category-1) * h;
  751.  
  752.         // found a weapon in this catagory
  753.         if (weaponToDraw == cg.weaponMenuSelect)
  754.         {    
  755.             // this is the currently selected weapon, so draw in green
  756.             Vector4Copy(colorSelected, colorDraw);
  757.             activeCategory = category;
  758.         }
  759.         else if ( (ps->stats[STAT_WEAPONS] & ( 1 << weaponToDraw )) )
  760.         {    
  761.             int ammoCount = 0;
  762.             
  763.             ammoCount += ps->ammo[weaponData[weaponToDraw].attack[ATTACK_NORMAL].ammoIndex];
  764.             ammoCount += ps->clip[ATTACK_NORMAL][weaponToDraw];
  765.             ammoCount += ps->ammo[weaponData[weaponToDraw].attack[ATTACK_ALTERNATE].ammoIndex];
  766.             ammoCount += ps->clip[ATTACK_ALTERNATE][weaponToDraw];
  767.  
  768.             if ( !ammoCount )
  769.             {    
  770.                 if (CAT_GRENADE <= category)
  771.                 {    
  772.                     // no grenades means no grenades
  773.                     continue;
  774.                 }
  775.                 else
  776.                 {    
  777.                     // weapon has no ammo so show it disabled
  778.                     Vector4Copy(colorDisabled, colorDraw );
  779.                 }
  780.             }
  781.             else
  782.             {    
  783.                 // draw in normal color
  784.                 Vector4Copy(colorNormal, colorDraw);
  785.             }
  786.         }
  787.         else
  788.         {    // don't have it, so don't draw
  789.             continue;
  790.         }
  791.  
  792.         icon = cg_weapons[ weaponToDraw ].weaponIcon;
  793.         if (icon)
  794.         {    
  795.             // draw weapon icon
  796.             if (CAT_GRENADE <= category)
  797.             {    
  798.                 // draw square icons
  799.                 trap_R_SetColor( colorShadow );
  800.                 CG_DrawPic( x+2, y+2, h * 0.90f, h * 0.90f, icon );
  801.  
  802.                 trap_R_SetColor( colorDraw );
  803.                 CG_DrawPic( x, y, h * 0.90f, h * 0.90f, icon );
  804.  
  805.                 category_x[category] += h;
  806.             }
  807.             else
  808.             {    
  809.                 // draw rectangular icons
  810.                 trap_R_SetColor( colorShadow );
  811.                 CG_DrawPic( x+2, y+2, w * 0.90f, h * 0.90f, icon );
  812.  
  813.                 trap_R_SetColor( colorDraw );
  814.                 CG_DrawPic( x, y, w * 0.90f, h * 0.90f, icon );
  815.  
  816.                 category_x[category] += w;
  817.             }
  818.         }
  819.  
  820.         trap_R_SetColor( NULL );
  821.     }
  822.  
  823.     // show weapon catagory numbers
  824.     for (i = CAT_NONE + 1; i < CAT_MAX; i++)
  825.     {
  826.         y = rect->y + (i - 1) * h;
  827.         Com_sprintf(numStr, sizeof(numStr),"%d", i );
  828.         wid = trap_R_GetTextWidth (numStr, font, 1.25f, 0 );
  829.         if (i == activeCategory)
  830.         {
  831.             Vector4Copy(colorSelected, colorDraw);
  832.         }
  833.         else
  834.         {
  835.             Vector4Copy(colorNormal, colorDraw);
  836.         }
  837.  
  838.         colorDraw[3] = 1.0f;
  839.  
  840.         CG_DrawText (rect->x + (w - wid) / 2 + 2, y, font, 0.6f, colorDraw, numStr, 0, DT_DROPSHADOW );
  841.     }
  842.  
  843.     item = BG_FindWeaponItem ( cg.weaponMenuSelect );
  844.     if ( item )
  845.     {
  846.         // Draw the selected weapons name
  847.         s = va("Weapon: %s", item->pickup_name);
  848.         w = trap_R_GetTextWidth ( s, cgs.media.hudFont, 0.43f, 0 );
  849.         CG_DrawText ( 640 - rect->x - w, rect->y, cgs.media.hudFont, 0.43f, colorSelected, s, 0, 0  );
  850.  
  851.         // Draw the selected weapons ammo count
  852.         if ( BG_WeaponHasAlternateAmmo ( cg.weaponMenuSelect ) )
  853.         {
  854.             s = va("Ammo: %i / %i", cg.predictedPlayerState.clip[ATTACK_NORMAL][cg.weaponMenuSelect] + cg.predictedPlayerState.ammo[weaponData[cg.weaponMenuSelect].attack[ATTACK_NORMAL].ammoIndex],
  855.                                     cg.predictedPlayerState.clip[ATTACK_ALTERNATE][cg.weaponMenuSelect] + cg.predictedPlayerState.ammo[weaponData[cg.weaponMenuSelect].attack[ATTACK_ALTERNATE].ammoIndex]);
  856.         }
  857.         else
  858.         {
  859.             s = va("Ammo: %i", cg.predictedPlayerState.clip[ATTACK_NORMAL][cg.weaponMenuSelect] + cg.predictedPlayerState.ammo[weaponData[cg.weaponMenuSelect].attack[ATTACK_NORMAL].ammoIndex]);
  860.         }
  861.  
  862.         w = trap_R_GetTextWidth ( s, cgs.media.hudFont, 0.43f, 0 );
  863.         CG_DrawText ( 640 - rect->x - w, rect->y + 15, cgs.media.hudFont, 0.43f, colorSelected, s, 0, 0  );
  864.     }
  865. }
  866.  
  867. const char *CG_GetGameStatusText() 
  868. {
  869.     const char *s = "";
  870.  
  871.     if ( !cgs.gametypeData->teams ) 
  872.     {
  873.         if (cg.snap->ps.persistant[PERS_TEAM] != TEAM_SPECTATOR ) 
  874.         {
  875.             s = va("%s place with %i",CG_PlaceString( cg.snap->ps.persistant[PERS_RANK] + 1 ),cg.snap->ps.persistant[PERS_SCORE] );
  876.         }
  877.     } 
  878.     else 
  879.     {
  880.         if ( cg.teamScores[0] == cg.teamScores[1] ) 
  881.         {
  882.             s = va("Teams are tied at %i", cg.teamScores[0] );
  883.         } 
  884.         else if ( cg.teamScores[0] >= cg.teamScores[1] ) 
  885.         {
  886.             s = va("Red leads Blue, %i to %i", cg.teamScores[0], cg.teamScores[1] );
  887.         } 
  888.         else 
  889.         {
  890.             s = va("Blue leads Red, %i to %i", cg.teamScores[1], cg.teamScores[0] );
  891.         }
  892.     }
  893.  
  894.     return s;
  895. }
  896.     
  897. static void CG_DrawGameStatus(rectDef_t *rect, qhandle_t font, float scale, vec4_t color ) 
  898. {
  899.     CG_DrawText (rect->x, rect->y + rect->h, font, scale, color, CG_GetGameStatusText(), 0 , 0 );
  900. }
  901.  
  902. const char *CG_GameTypeString() 
  903. {
  904.     return cgs.gametypeData->displayName;
  905. }
  906.  
  907. static void CG_DrawGameType(rectDef_t *rect, qhandle_t font, float scale, vec4_t color ) 
  908. {
  909.     CG_DrawText (rect->x, rect->y + rect->h, font, scale, color, CG_GameTypeString(), 0, 0  );
  910. }
  911.  
  912. void CG_OwnerDraw ( float x, float y, float w, float h, float text_x, float text_y, int ownerDraw, int ownerDrawFlags, int align, float special, qhandle_t font, float scale, vec4_t color, qhandle_t shader, int textStyle, const char* param ) 
  913. {
  914.     rectDef_t rect;
  915.  
  916.     rect.x = x;
  917.     rect.y = y;
  918.     rect.w = w;
  919.     rect.h = h;
  920.  
  921.     switch (ownerDraw) 
  922.     {    
  923.         case CG_USE_ICON:
  924.             CG_DrawUseIcon ( &rect );
  925.             break;
  926.  
  927.         case CG_PLAYER_GAMETYPE_ITEMS:
  928.             CG_DrawPlayerGametypeItems ( &rect );
  929.             break;
  930.  
  931.         case CG_PLAYER_ARMOR:
  932.             CG_DrawPlayerArmor ( &rect );
  933.             break;
  934.  
  935.         case CG_PLAYER_WEAPON_AMMO:
  936.             CG_DrawPlayerWeaponAmmo(&rect, font, scale, color );
  937.             break;
  938.  
  939.         case CG_PLAYER_WEAPON_CLIP:
  940.             CG_DrawPlayerWeaponClip(&rect, font, scale, color );
  941.             break;
  942.  
  943.         case CG_PLAYER_WEAPON_NAME:
  944.             CG_DrawPlayerWeaponName(&rect, font, scale, color );
  945.             break;
  946.  
  947.         case CG_PLAYER_ALT_WEAPON_NAME:
  948.             CG_DrawPlayerAltWeaponName(&rect, font, scale, color );
  949.             break;
  950.  
  951.         case CG_PLAYER_ALT_WEAPON_AMMO:
  952.             CG_DrawPlayerAltWeaponAmmo(&rect, font, scale, color );
  953.             break;
  954.  
  955.         case CG_PLAYER_ALT_WEAPON_AMMOICON:
  956.             CG_DrawPlayerAltWeaponAmmoIcon ( &rect, color );
  957.             break;
  958.  
  959.         case CG_PLAYER_WEAPON_MODE:
  960.             CG_DrawPlayerWeaponMode(&rect, font, scale, color );
  961.             break;
  962.  
  963.         case CG_PLAYER_SCORE:
  964.             CG_DrawPlayerScore(&rect, font, scale, color );
  965.             break;
  966.  
  967.         case CG_GAME_TYPE:
  968.             CG_DrawGameType(&rect, font, scale, color );
  969.             break;
  970.  
  971.         case CG_RED_SCORE:
  972.             CG_DrawRedScore(&rect, font, scale, color );
  973.             break;
  974.  
  975.         case CG_BLUE_SCORE:
  976.             CG_DrawBlueScore(&rect, font, scale, color );
  977.             break;
  978.  
  979.         case CG_GAME_STATUS:
  980.             CG_DrawGameStatus(&rect, font, scale, color );
  981.             break;
  982.  
  983.         case CG_1STPLACE:
  984.             CG_Draw1stPlace(&rect, font, scale, color );
  985.             break;
  986.  
  987.         case CG_2NDPLACE:
  988.             CG_Draw2ndPlace(&rect, font, scale, color );
  989.             break;
  990.  
  991.         case CG_WEAPON_LIST:
  992.             CG_DrawWeaponList(&rect, font, scale, color );
  993.             break;
  994.  
  995.         case CG_PLAYER_LOCATION:
  996.             CG_DrawPlayerLocation(&rect, scale, color, textStyle);
  997.             break;
  998.  
  999.         case CG_PLAYER_SNIPER_BULLET_1:
  1000.         case CG_PLAYER_SNIPER_BULLET_2:
  1001.         case CG_PLAYER_SNIPER_BULLET_3:
  1002.         case CG_PLAYER_SNIPER_BULLET_4:
  1003.         case CG_PLAYER_SNIPER_BULLET_5:
  1004.         case CG_PLAYER_SNIPER_BULLET_6:
  1005.             CG_DrawPlayerSniperBullet ( &rect, shader, ownerDraw - CG_PLAYER_SNIPER_BULLET_1 + 1);
  1006.             break;
  1007.  
  1008.         case CG_PLAYER_SNIPER_MAGNIFICATION:
  1009.             CG_DrawPlayerSniperMagnification ( &rect, font, scale, color );
  1010.             break;
  1011.  
  1012.         default:
  1013.             break;
  1014.     }
  1015. }
  1016.  
  1017. void CG_MouseEvent(int x, int y) 
  1018. {
  1019.     int n;
  1020.  
  1021.     if ( (cg.predictedPlayerState.pm_type == PM_NORMAL || cg.predictedPlayerState.pm_type == PM_SPECTATOR) && cg.showScores == qfalse) 
  1022.     {
  1023.         trap_Key_SetCatcher(0);
  1024.         return;
  1025.     }
  1026.  
  1027.     cgs.cursorX+= x;
  1028.     if (cgs.cursorX < 0)
  1029.     {
  1030.         cgs.cursorX = 0;
  1031.     }
  1032.     else if (cgs.cursorX > 640)
  1033.     {
  1034.         cgs.cursorX = 640;
  1035.     }
  1036.  
  1037.     cgs.cursorY += y;
  1038.     if (cgs.cursorY < 0)
  1039.     {
  1040.         cgs.cursorY = 0;
  1041.     }
  1042.     else if (cgs.cursorY > 480)
  1043.     {
  1044.         cgs.cursorY = 480;
  1045.     }
  1046.  
  1047.     n = Display_CursorType(cgs.cursorX, cgs.cursorY);
  1048.     cgs.activeCursor = 0;
  1049.     if (n == CURSOR_ARROW) 
  1050.     {
  1051.         cgs.activeCursor = cgs.media.cursor;
  1052.     } 
  1053.     else if (n == CURSOR_SIZER) 
  1054.     {
  1055.         cgs.activeCursor = cgs.media.cursor;
  1056.     }
  1057.  
  1058.     if (cgs.capturedItem) 
  1059.     {
  1060.         Display_MouseMove(cgs.capturedItem, x, y);
  1061.     } 
  1062.     else 
  1063.     {
  1064.         Display_MouseMove(NULL, cgs.cursorX, cgs.cursorY);
  1065.     }
  1066. }
  1067.  
  1068. /*
  1069. ==================
  1070. CG_EventHandling
  1071. ==================
  1072.  type 0 - no event handling
  1073.       1 - team menu
  1074.       2 - hud editor
  1075.  
  1076. */
  1077. void CG_EventHandling(int type) 
  1078. {
  1079.     cgs.eventHandling = type;  
  1080. }
  1081.  
  1082.  
  1083. void CG_KeyEvent(int key, qboolean down) 
  1084. {
  1085.     if (!down) 
  1086.     {
  1087.         return;
  1088.     }
  1089.  
  1090.     if ( cg.predictedPlayerState.pm_type == PM_NORMAL || (cg.predictedPlayerState.pm_type == PM_SPECTATOR && cg.showScores == qfalse)) 
  1091.     {
  1092.         CG_EventHandling(CGAME_EVENT_NONE);
  1093.         trap_Key_SetCatcher(0);
  1094.         return;
  1095.     }
  1096.  
  1097.     Display_HandleKey(key, down, cgs.cursorX, cgs.cursorY);
  1098.  
  1099.     if (cgs.capturedItem) 
  1100.     {
  1101.         cgs.capturedItem = NULL;
  1102.     }    
  1103.     else 
  1104.     {
  1105.         if (key == K_MOUSE2 && down) 
  1106.         {
  1107.             cgs.capturedItem = Display_CaptureItem(cgs.cursorX, cgs.cursorY);
  1108.         }
  1109.     }
  1110. }
  1111.  
  1112. void CG_RunMenuScript(const char **args) 
  1113. {
  1114. }
  1115.  
  1116.  
  1117. void CG_GetTeamColor(vec4_t *color) 
  1118. {
  1119.   if (cg.snap->ps.persistant[PERS_TEAM] == TEAM_RED) {
  1120.     (*color)[0] = 1.0f;
  1121.     (*color)[3] = 0.25f;
  1122.     (*color)[1] = (*color)[2] = 0.0f;
  1123.   } else if (cg.snap->ps.persistant[PERS_TEAM] == TEAM_BLUE) {
  1124.     (*color)[0] = (*color)[1] = 0.0f;
  1125.     (*color)[2] = 1.0f;
  1126.     (*color)[3] = 0.25f;
  1127.   } else {
  1128.     (*color)[0] = (*color)[2] = 0.0f;
  1129.     (*color)[1] = 0.17f;
  1130.     (*color)[3] = 0.25f;
  1131.     }
  1132. }
  1133.  
  1134.